import uuid
from datetime import datetime
from typing import List, Optional, Dict, Any, Tuple

from loguru import logger
from sqlalchemy import select, func, and_
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload

from ..models import Base, KnowledgeBase, UploadedFile, KnowledgeBaseFile


class KnowledgeService:
    """知识库服务类"""

    def __init__(self):
        self.engine = None

    async def _get_engine(self):
        """获取数据库引擎"""
        if self.engine is None:
            from ..config.resource import get_db_engine
            self.engine = get_db_engine()
        return self.engine

    async def init_tables(self):
        """初始化数据库表"""
        try:
            engine = await self._get_engine()
            async with engine.begin() as conn:
                await conn.run_sync(Base.metadata.create_all)
            logger.info("知识库表初始化完成")
        except Exception as e:
            logger.exception(f"知识库表初始化失败: {e}")
            raise

    # 知识库管理
    async def create_knowledge_base(
        self,
        name: str,
        description: str = None,
        initial_settings: Dict[str, Any] = None
    ) -> KnowledgeBase:
        """创建知识库"""
        try:
            engine = await self._get_engine()
            async with AsyncSession(engine) as session:
                # 检查名称是否重复
                stmt = select(KnowledgeBase).where(KnowledgeBase.name == name)
                existing = await session.execute(stmt)
                if existing.scalars().first():
                    raise ValueError(f"知识库名称 '{name}' 已存在")

                # 准备设置
                settings_data = initial_settings or {}

                # 创建知识库
                kb = KnowledgeBase(
                    id=str(uuid.uuid4()),
                    name=name,
                    description=description,
                    status='active',
                    settings=settings_data
                )

                session.add(kb)
                await session.commit()
                await session.refresh(kb)

                logger.info(f"创建知识库成功: {kb.id} - {name}, 设置: {settings_data}")
                return kb

        except Exception as e:
            logger.exception(f"创建知识库失败: {e}")
            raise

    async def get_knowledge_base(self, kb_id: str) -> Optional[KnowledgeBase]:
        """获取知识库详情"""
        try:
            engine = await self._get_engine()
            async with AsyncSession(engine) as session:
                stmt = (
                    select(KnowledgeBase)
                    .options(selectinload(KnowledgeBase.files).selectinload(KnowledgeBaseFile.file))
                    .where(KnowledgeBase.id == kb_id)
                )
                result = await session.execute(stmt)
                return result.scalars().first()

        except Exception as e:
            logger.exception(f"获取知识库失败: {e}")
            return None

    async def list_knowledge_bases(
        self,
        limit: int = 50,
        offset: int = 0,
        status: str = None
    ) -> Tuple[List[KnowledgeBase], int]:
        """获取知识库列表"""
        try:
            engine = await self._get_engine()
            async with AsyncSession(engine) as session:
                # 构建查询条件
                conditions = []
                if status:
                    conditions.append(KnowledgeBase.status == status)

                # 查询数据
                stmt = select(KnowledgeBase)
                if conditions:
                    stmt = stmt.where(and_(*conditions))
                stmt = stmt.order_by(KnowledgeBase.updated_at.desc()).limit(limit).offset(offset)

                result = await session.execute(stmt)
                kbs = result.scalars().all()

                # 查询总数
                count_stmt = select(func.count(KnowledgeBase.id))
                if conditions:
                    count_stmt = count_stmt.where(and_(*conditions))
                count_result = await session.execute(count_stmt)
                total = count_result.scalar()

                return list(kbs), total

        except Exception as e:
            logger.exception(f"获取知识库列表失败: {e}")
            return [], 0

    async def update_knowledge_base(
        self,
        kb_id: str,
        name: str = None,
        description: str = None,
        status: str = None
    ) -> Optional[KnowledgeBase]:
        """更新知识库"""
        try:
            engine = await self._get_engine()
            async with AsyncSession(engine) as session:
                kb = await session.get(KnowledgeBase, kb_id)
                if not kb:
                    return None

                # 检查名称是否重复（如果要修改名称）
                if name and name != kb.name:
                    stmt = select(KnowledgeBase).where(
                        and_(KnowledgeBase.name == name, KnowledgeBase.id != kb_id)
                    )
                    existing = await session.execute(stmt)
                    if existing.scalars().first():
                        raise ValueError(f"知识库名称 '{name}' 已存在")
                    kb.name = name

                # 更新其他字段
                if description is not None:
                    kb.description = description
                if status:
                    kb.status = status

                kb.updated_at = datetime.now()
                await session.commit()
                await session.refresh(kb)

                logger.info(f"更新知识库成功: {kb_id}")
                return kb

        except Exception as e:
            logger.exception(f"更新知识库失败: {e}")
            raise

    async def delete_knowledge_base(self, kb_id: str) -> bool:
        """删除知识库"""
        try:
            engine = await self._get_engine()
            async with AsyncSession(engine) as session:
                kb = await session.get(KnowledgeBase, kb_id)
                if not kb:
                    return False

                await session.delete(kb)
                await session.commit()

                logger.info(f"删除知识库成功: {kb_id}")
                return True

        except Exception as e:
            logger.exception(f"删除知识库失败: {e}")
            return False

    # 文件管理
    async def create_uploaded_file(
        self,
        filename: str,
        original_filename: str,
        file_path: str,
        file_size: int,
        file_type: str,
        mime_type: str = None
    ) -> UploadedFile:
        """创建上传文件记录"""
        try:
            engine = await self._get_engine()
            async with AsyncSession(engine) as session:
                file_record = UploadedFile(
                    id=str(uuid.uuid4()),
                    filename=filename,
                    original_filename=original_filename,
                    file_path=file_path,
                    file_size=file_size,
                    file_type=file_type,
                    mime_type=mime_type,
                    is_processed=False
                )

                session.add(file_record)
                await session.commit()
                await session.refresh(file_record)

                logger.info(f"创建文件记录成功: {file_record.id} - {filename}")
                return file_record

        except Exception as e:
            logger.exception(f"创建文件记录失败: {e}")
            raise

    async def get_uploaded_file(self, file_id: str) -> Optional[UploadedFile]:
        """获取上传文件详情"""
        try:
            engine = await self._get_engine()
            async with AsyncSession(engine) as session:
                return await session.get(UploadedFile, file_id)

        except Exception as e:
            logger.exception(f"获取文件详情失败: {e}")
            return None

    async def list_uploaded_files(
        self,
        limit: int = 50,
        offset: int = 0,
        file_type: str = None,
        is_processed: bool = None
    ) -> Tuple[List[UploadedFile], int]:
        """获取上传文件列表"""
        try:
            engine = await self._get_engine()
            async with AsyncSession(engine) as session:
                # 构建查询条件
                conditions = []
                if file_type:
                    conditions.append(UploadedFile.file_type == file_type)
                if is_processed is not None:
                    conditions.append(UploadedFile.is_processed == is_processed)

                # 查询数据
                stmt = select(UploadedFile)
                if conditions:
                    stmt = stmt.where(and_(*conditions))
                stmt = stmt.order_by(UploadedFile.created_at.desc()).limit(limit).offset(offset)

                result = await session.execute(stmt)
                files = result.scalars().all()

                # 查询总数
                count_stmt = select(func.count(UploadedFile.id))
                if conditions:
                    count_stmt = count_stmt.where(and_(*conditions))
                count_result = await session.execute(count_stmt)
                total = count_result.scalar()

                return list(files), total

        except Exception as e:
            logger.exception(f"获取文件列表失败: {e}")
            return [], 0

    async def delete_uploaded_file(self, file_id: str) -> bool:
        """删除上传文件记录"""
        try:
            engine = await self._get_engine()
            async with AsyncSession(engine) as session:
                file_record = await session.get(UploadedFile, file_id)
                if not file_record:
                    return False

                # 先删除所有关联的knowledge_base_files记录
                kb_files_stmt = select(KnowledgeBaseFile).where(KnowledgeBaseFile.file_id == file_id)
                kb_files_result = await session.execute(kb_files_stmt)
                kb_files = kb_files_result.scalars().all()
                
                for kb_file in kb_files:
                    await session.delete(kb_file)
                    logger.info(f"删除知识库文件关联记录: {kb_file.id} (知识库: {kb_file.knowledge_base_id})")

                # 然后删除文件记录
                await session.delete(file_record)
                await session.commit()

                logger.info(f"删除文件记录成功: {file_id}, 同时删除了 {len(kb_files)} 条关联记录")
                return True

        except Exception as e:
            logger.exception(f"删除文件记录失败: {e}")
            return False

    # 知识库文件关联管理
    async def add_files_to_knowledge_base(
        self,
        kb_id: str,
        file_ids: List[str]
    ) -> Tuple[List[KnowledgeBaseFile], List[str]]:
        """添加文件到知识库"""
        try:
            engine = await self._get_engine()
            async with AsyncSession(engine) as session:
                # 检查知识库是否存在
                kb = await session.get(KnowledgeBase, kb_id)
                if not kb:
                    raise ValueError(f"知识库不存在: {kb_id}")

                added_files = []
                failed_files = []

                for file_id in file_ids:
                    try:
                        # 检查文件是否存在
                        file_record = await session.get(UploadedFile, file_id)
                        if not file_record:
                            failed_files.append(f"文件不存在: {file_id}")
                            continue

                        # 检查是否已经添加过
                        stmt = select(KnowledgeBaseFile).where(
                            and_(
                                KnowledgeBaseFile.knowledge_base_id == kb_id,
                                KnowledgeBaseFile.file_id == file_id
                            )
                        )
                        existing = await session.execute(stmt)
                        if existing.scalars().first():
                            failed_files.append(f"文件已存在于知识库: {file_id}")
                            continue

                        # 创建关联记录
                        kb_file = KnowledgeBaseFile(
                            id=str(uuid.uuid4()),
                            knowledge_base_id=kb_id,
                            file_id=file_id,
                            status='pending'  # 初始状态为pending，处理时会更新为processing
                        )

                        session.add(kb_file)
                        added_files.append(kb_file)

                    except Exception as e:
                        failed_files.append(f"添加文件失败 {file_id}: {str(e)}")

                # 更新知识库的更新时间
                kb.updated_at = datetime.now()
                await session.commit()

                # 刷新添加的文件记录
                for kb_file in added_files:
                    await session.refresh(kb_file)

                logger.info(f"添加文件到知识库: {kb_id}, 成功: {len(added_files)}, 失败: {len(failed_files)}")
                return added_files, failed_files

        except Exception as e:
            logger.exception(f"添加文件到知识库失败: {e}")
            raise

    async def remove_files_from_knowledge_base(
        self,
        kb_id: str,
        file_ids: List[str]
    ) -> Tuple[int, List[str]]:
        """从知识库移除文件"""
        try:
            engine = await self._get_engine()
            async with AsyncSession(engine) as session:
                # 检查知识库是否存在
                kb = await session.get(KnowledgeBase, kb_id)
                if not kb:
                    raise ValueError(f"知识库不存在: {kb_id}")

                removed_count = 0
                failed_files = []

                for file_id in file_ids:
                    try:
                        # 查找关联记录
                        stmt = select(KnowledgeBaseFile).where(
                            and_(
                                KnowledgeBaseFile.knowledge_base_id == kb_id,
                                KnowledgeBaseFile.file_id == file_id
                            )
                        )
                        result = await session.execute(stmt)
                        kb_file = result.scalars().first()

                        if kb_file:
                            await session.delete(kb_file)
                            removed_count += 1
                        else:
                            failed_files.append(f"文件不在知识库中: {file_id}")

                    except Exception as e:
                        failed_files.append(f"移除文件失败 {file_id}: {str(e)}")

                # 更新知识库的更新时间
                kb.updated_at = datetime.now()
                await session.commit()

                logger.info(f"从知识库移除文件: {kb_id}, 成功: {removed_count}, 失败: {len(failed_files)}")
                return removed_count, failed_files

        except Exception as e:
            logger.exception(f"从知识库移除文件失败: {e}")
            raise

    async def get_knowledge_base_files(
        self,
        kb_id: str,
        limit: int = 50,
        offset: int = 0,
        status: str = None
    ) -> Tuple[List[KnowledgeBaseFile], int]:
        """获取知识库文件列表"""
        try:
            engine = await self._get_engine()
            async with AsyncSession(engine) as session:
                # 构建查询条件
                conditions = [KnowledgeBaseFile.knowledge_base_id == kb_id]
                if status:
                    conditions.append(KnowledgeBaseFile.status == status)

                # 查询数据
                stmt = (
                    select(KnowledgeBaseFile)
                    .options(selectinload(KnowledgeBaseFile.file))
                    .where(and_(*conditions))
                    .order_by(KnowledgeBaseFile.added_at.desc())
                    .limit(limit)
                    .offset(offset)
                )

                result = await session.execute(stmt)
                kb_files = result.scalars().all()

                # 查询总数
                count_stmt = select(func.count(KnowledgeBaseFile.id)).where(and_(*conditions))
                count_result = await session.execute(count_stmt)
                total = count_result.scalar()

                return list(kb_files), total

        except Exception as e:
            logger.exception(f"获取知识库文件列表失败: {e}")
            return [], 0

    async def update_knowledge_base_file_status(
        self,
        kb_id: str,
        file_id: str = None,
        object_name: str = None,
        status: str = "completed"
    ) -> bool:
        """更新知识库文件状态"""
        try:
            engine = await self._get_engine()
            async with AsyncSession(engine) as session:
                # 根据file_id或object_name查找knowledge_base_files记录
                if file_id:
                    # 直接通过file_id查找
                    stmt = select(KnowledgeBaseFile).where(
                        and_(
                            KnowledgeBaseFile.knowledge_base_id == kb_id,
                            KnowledgeBaseFile.file_id == file_id
                        )
                    )
                elif object_name:
                    # 通过object_name查找文件，再查找关联记录
                    file_stmt = select(UploadedFile).where(UploadedFile.file_path == object_name)
                    file_result = await session.execute(file_stmt)
                    file_record = file_result.scalars().first()
                    
                    if not file_record:
                        logger.warning(f"未找到object_name为 {object_name} 的文件记录")
                        return False
                    
                    stmt = select(KnowledgeBaseFile).where(
                        and_(
                            KnowledgeBaseFile.knowledge_base_id == kb_id,
                            KnowledgeBaseFile.file_id == file_record.id
                        )
                    )
                else:
                    logger.error("必须提供file_id或object_name参数")
                    return False

                result = await session.execute(stmt)
                kb_file = result.scalars().first()

                if not kb_file:
                    logger.warning(f"未找到知识库文件关联记录: kb_id={kb_id}, file_id={file_id}, object_name={object_name}")
                    return False

                # 更新状态
                old_status = kb_file.status
                kb_file.status = status
                await session.commit()
                logger.info(f"更新知识库文件状态成功: {kb_file.id} ({old_status} -> {status})")
                return True

        except Exception as e:
            logger.exception(f"更新知识库文件状态失败: {e}")
            return False

    async def get_knowledge_base_statistics(self, kb_id: str) -> Dict[str, Any]:
        """获取知识库统计信息"""
        try:
            engine = await self._get_engine()
            async with AsyncSession(engine) as session:
                # 获取文件总数
                file_count_stmt = select(func.count(KnowledgeBaseFile.id)).where(
                    KnowledgeBaseFile.knowledge_base_id == kb_id
                )
                file_count_result = await session.execute(file_count_stmt)
                file_count = file_count_result.scalar()

                # 获取不同状态的文件数量
                status_stmt = (
                    select(KnowledgeBaseFile.status, func.count(KnowledgeBaseFile.id))
                    .where(KnowledgeBaseFile.knowledge_base_id == kb_id)
                    .group_by(KnowledgeBaseFile.status)
                )
                status_result = await session.execute(status_stmt)
                status_counts = {status: count for status, count in status_result.all()}

                # 获取文件总大小
                size_stmt = (
                    select(func.sum(UploadedFile.file_size))
                    .select_from(
                        KnowledgeBaseFile.__table__.join(
                            UploadedFile.__table__,
                            KnowledgeBaseFile.file_id == UploadedFile.id
                        )
                    )
                    .where(KnowledgeBaseFile.knowledge_base_id == kb_id)
                )
                size_result = await session.execute(size_stmt)
                total_size = size_result.scalar() or 0

                return {
                    'file_count': file_count,
                    'status_counts': status_counts,
                    'total_size': total_size
                }

        except Exception as e:
            logger.exception(f"获取知识库统计信息失败: {e}")
            return {
                'file_count': 0,
                'status_counts': {},
                'total_size': 0
            }

    # 知识库设置管理
    async def get_knowledge_base_settings(self, kb_id: str):
        """获取知识库设置"""
        try:
            from ai_platform.api.knowledge import KnowledgeBaseSettings
            engine = await self._get_engine()
            async with AsyncSession(engine) as session:
                kb = await session.get(KnowledgeBase, kb_id)
                if not kb:
                    return None
                # 如果没有设置，返回默认设置
                if not kb.settings:
                    return KnowledgeBaseSettings()
                return KnowledgeBaseSettings(**kb.settings)
        except Exception as e:
            logger.exception(f"获取知识库设置失败: {e}")
            return None

    async def update_knowledge_base_settings(
        self,
        kb_id: str,
        settings: Dict[str, Any]
    ) -> Optional[Dict[str, Any]]:
        """更新知识库设置"""
        try:
            engine = await self._get_engine()
            async with AsyncSession(engine) as session:
                kb = await session.get(KnowledgeBase, kb_id)
                if not kb:
                    return None

                # 验证设置参数
                validated_settings = self._validate_settings(settings)

                # 更新设置
                kb.settings = validated_settings
                kb.updated_at = datetime.now()

                await session.commit()
                await session.refresh(kb)

                logger.info(f"更新知识库设置成功: {kb_id}")
                return validated_settings

        except Exception as e:
            logger.exception(f"更新知识库设置失败: {e}")
            raise

    @staticmethod
    def _validate_settings(settings: Dict[str, Any]) -> Dict[str, Any]:
        """验证和标准化设置参数"""
        validated = {}

        # chunk_size 验证 (100-4000)
        chunk_size = settings.get('chunk_size', 1000)
        if not isinstance(chunk_size, int) or chunk_size < 100 or chunk_size > 4000:
            raise ValueError("chunk_size 必须是 100-4000 之间的整数")
        validated['chunk_size'] = chunk_size

        # chunk_overlap 验证 (0-500, 必须小于 chunk_size)
        chunk_overlap = settings.get('chunk_overlap', 200)
        if not isinstance(chunk_overlap, int) or chunk_overlap < 0 or chunk_overlap > 500:
            raise ValueError("chunk_overlap 必须是 0-500 之间的整数")
        if chunk_overlap >= chunk_size:
            raise ValueError("chunk_overlap 必须小于 chunk_size")
        validated['chunk_overlap'] = chunk_overlap

        # text_split_strategy 验证
        strategy = settings.get('text_split_strategy', 'fixed_chars')
        if strategy not in ['fixed_chars', 'semantic']:
            raise ValueError("text_split_strategy 必须是 'fixed_chars' 或 'semantic'")
        validated['text_split_strategy'] = strategy

        # split_chars 验证
        split_chars = settings.get('split_chars', ['\n\n', '\n', '。', '！', '？', '；'])
        if not isinstance(split_chars, list):
            raise ValueError("split_chars 必须是字符串数组")
        validated['split_chars'] = split_chars

        # index_type 验证
        index_type = settings.get('index_type', 'vector')
        if index_type not in ['vector', 'knowledge_graph', 'long_document']:
            raise ValueError("index_type 必须是 'vector'、'knowledge_graph' 或 'long_document'")
        validated['index_type'] = index_type

        return validated

    async def get_knowledge_base_data_chunks(
        self,
        kb_id: str,
        limit: int = 50,
        offset: int = 0,
        search_query: str = None
    ) -> Tuple[List[Dict[str, Any]], int]:
        """获取知识库的数据片段"""
        kb = await self.get_knowledge_base(kb_id)
        if not kb:
            return [], 0

        chunks = []
        total = 0

        try:
            # 方法1: 直接查询 data_data_vector_store 表
            logger.info(f"直接查询 data_data_vector_store 表获取知识库 {kb_id} 的数据")

            engine = await self._get_engine()
            async with AsyncSession(engine) as session:
                from sqlalchemy import text, func

                # 构建基础查询条件
                base_conditions = "metadata_->>'knowledge_base_id' = :kb_id"
                params = {"kb_id": kb_id}

                # 如果有搜索查询，添加文本搜索条件
                if search_query:
                    # 使用PostgreSQL的全文搜索功能
                    base_conditions += " AND (text ILIKE :search_text OR metadata_->>'title' ILIKE :search_title)"
                    params["search_text"] = f"%{search_query}%"
                    params["search_title"] = f"%{search_query}%"

                # 查询总数
                count_sql = f"SELECT COUNT(*) FROM data_data_vector_store WHERE {base_conditions}"
                count_result = await session.execute(text(count_sql), params)
                total = count_result.scalar() or 0

                if total == 0:
                    logger.info(f"在向量表中未找到属于知识库 {kb_id} 的数据")
                else:
                    # 查询数据
                    data_sql = f"""
                    SELECT id, text, metadata_, node_id
                    FROM data_data_vector_store 
                    WHERE {base_conditions}
                    ORDER BY id DESC
                    LIMIT :limit OFFSET :offset
                    """
                    params.update({"limit": limit, "offset": offset})

                    data_result = await session.execute(text(data_sql), params)
                    rows = data_result.fetchall()

                    logger.info(f"从向量表获取到 {len(rows)} 条数据")

                    for i, row in enumerate(rows):
                        try:
                            # 解析元数据
                            metadata = row.metadata_ or {}

                            chunk_data = {
                                'id': row.node_id or str(row.id),
                                'title': metadata.get('title', metadata.get('file_name', f'数据片段 #{offset + i + 1}')),
                                'content': row.text[:500] + '...' if len(row.text) > 500 else row.text,
                                'source': metadata.get('source', metadata.get('file_name', metadata.get('object_name', '未知来源'))),
                                'type': metadata.get('type', 'TEXT'),
                                'chunk_index': offset + i + 1,
                                'word_count': len(row.text),
                                'score': metadata.get('score', 1.0),
                                'created_at': metadata.get('created_at', metadata.get('processed_at', datetime.now().isoformat())),
                                'full_content': row.text,
                                # 额外的元数据信息
                                'node_id': row.node_id,
                                'vector_id': row.id,
                                'metadata': metadata
                            }

                            # 如果有搜索查询，计算相关性得分
                            if search_query:
                                query_lower = search_query.lower()
                                text_lower = row.text.lower()
                                title_lower = chunk_data['title'].lower()

                                # 简单的相关性计算
                                title_matches = title_lower.count(query_lower) * 2  # 标题匹配权重更高
                                content_matches = text_lower.count(query_lower)
                                total_words = len(text_lower.split())

                                chunk_data['score'] = (title_matches + content_matches) / max(total_words, 1)

                            chunks.append(chunk_data)

                        except Exception as e:
                            logger.warning(f"处理向量数据记录失败: {e}")
                            continue

            # 如果有搜索查询，按相关性得分排序
            if search_query and chunks:
                chunks.sort(key=lambda x: x['score'], reverse=True)

            logger.info(f"从向量表成功获取 {len(chunks)} 个数据片段，总计 {total} 个")
            return chunks, total

        except Exception as e:
            logger.warning(f"直接查询向量表失败: {e}")

        logger.info(f"获取知识库 {kb_id} 数据片段完成，共 {total} 个片段，返回 {len(chunks)} 个")
        return chunks, total

    async def search_knowledge_base_data(
        self,
        kb_id: str,
        query: str,
        limit: int = 10
    ) -> List[Dict[str, Any]]:
        """搜索知识库数据"""
        try:
            # 检查知识库是否存在
            kb = await self.get_knowledge_base(kb_id)
            if not kb:
                return []

            # 使用向量搜索
            try:
                from ..config.resource import get_vector_index
                vector_index = get_vector_index()

                # 执行向量搜索
                query_engine = vector_index.as_query_engine(similarity_top_k=limit)
                response = query_engine.query(query)

                # 处理搜索结果
                search_results = []
                if hasattr(response, 'source_nodes'):
                    for i, node in enumerate(response.source_nodes):
                        result_data = {
                            'id': node.node_id or f"search_result_{i + 1}",
                            'title': node.metadata.get('title', f'搜索结果 #{i + 1}') if hasattr(node, 'metadata') and node.metadata else f'搜索结果 #{i + 1}',
                            'content': node.text[:500] + '...' if len(node.text) > 500 else node.text,
                            'source': node.metadata.get('source', '未知来源') if hasattr(node, 'metadata') and node.metadata else '未知来源',
                            'type': 'SEARCH_RESULT',
                            'score': node.score if hasattr(node, 'score') else 0.0,
                            'created_at': datetime.now().isoformat(),
                            'word_count': len(node.text),
                            'full_content': node.text
                        }
                        search_results.append(result_data)

                logger.info(f"知识库 {kb_id} 搜索完成，查询: '{query}'，结果数: {len(search_results)}")
                return search_results

            except Exception as e:
                logger.warning(f"向量搜索失败: {e}，使用简单文本搜索")

                # 如果向量搜索失败，使用简单的文本搜索
                chunks, _ = await self.get_knowledge_base_data_chunks(kb_id, limit=100, search_query=query)
                return chunks[:limit]

        except Exception as e:
            logger.exception(f"搜索知识库数据失败: {e}")
            return []


# 全局知识库服务实例
knowledge_service = KnowledgeService()
